{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "############## PLEASE RUN THIS CELL FIRST! ###################\n",
    "\n",
    "# import everything and define a test runner function\n",
    "from importlib import reload\n",
    "from helper import run\n",
    "import ecc\n",
    "import helper\n",
    "import tx\n",
    "import script"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tx import Tx\n",
    "from io import BytesIO\n",
    "raw_tx = ('0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000006b483045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed01210349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278afeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac19430600')\n",
    "stream = BytesIO(bytes.fromhex(raw_tx))\n",
    "transaction = Tx.parse(stream)\n",
    "print(transaction.fee() >= 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ecc import S256Point, Signature\n",
    "sec = bytes.fromhex('0349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278a')\n",
    "der = bytes.fromhex('3045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed')\n",
    "z = 0x27e0c5994dec7824e56dec6b2fcb342eb7cdb0d0957c2fce9882f715e85d81a6\n",
    "point = S256Point.parse(sec)\n",
    "signature = Signature.parse(der)\n",
    "print(point.verify(z, signature))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from helper import hash256\n",
    "modified_tx = bytes.fromhex('0100000001813f79011acb80925dfe69b3def355fe914bd1d96a3f5f71bf8303c6a989c7d1000000001976a914a802fc56c704ce87c42d7c92eb75e7896bdc41ae88acfeffffff02a135ef01000000001976a914bc3b654dca7e56b04dca18f2566cdaf02e8d9ada88ac99c39800000000001976a9141c4bc762dd5423e332166702cb75f40df79fea1288ac1943060001000000')\n",
    "h256 = hash256(modified_tx)\n",
    "z = int.from_bytes(h256, 'big')\n",
    "print(hex(z))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ecc import S256Point, Signature\n",
    "sec = bytes.fromhex('0349fc4e631e3624a545de3f89f5d8684c7b8138bd94bdd531d2e213bf016b278a')\n",
    "der = bytes.fromhex('3045022100ed81ff192e75a3fd2304004dcadb746fa5e24c5031ccfcf21320b0277457c98f02207a986d955c6e0cb35d446a89d3f56100f4d7f67801c31967743a9c8e10615bed')\n",
    "z = 0x27e0c5994dec7824e56dec6b2fcb342eb7cdb0d0957c2fce9882f715e85d81a6\n",
    "point = S256Point.parse(sec)\n",
    "signature = Signature.parse(der)\n",
    "point.verify(z, signature)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 1\n",
    "\n",
    "Write the `sig_hash` method for the `Tx` class.\n",
    "\n",
    "#### Make [this test](/edit/code-ch07/tx.py) pass: `tx.py:TxTest:test_sig_hash`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercise 1\n",
    "\n",
    "reload(tx)\n",
    "run(tx.TxTest(\"test_sig_hash\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 2\n",
    "\n",
    "Write the `verify_input` method for the `Tx` class. You will want to use the `TxIn.script_pubkey()`, `Tx.sig_hash()` and `Script.evaluate()` methods.\n",
    "\n",
    "#### Make [this test](/edit/code-ch07/tx.py) pass: `tx.py:TxTest:test_verify_p2pkh`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercise 2\n",
    "\n",
    "reload(tx)\n",
    "run(tx.TxTest(\"test_verify_p2pkh\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from helper import decode_base58, SIGHASH_ALL\n",
    "from script import p2pkh_script, Script\n",
    "from tx import TxIn, TxOut, Tx\n",
    "prev_tx = bytes.fromhex('0d6fe5213c0b3291f208cba8bfb59b7476dffacc4e5cb66f6eb20a080843a299')\n",
    "prev_index = 13\n",
    "tx_in = TxIn(prev_tx, prev_index)\n",
    "tx_outs = []\n",
    "change_amount = int(0.33*100000000)\n",
    "change_h160 = decode_base58('mzx5YhAH9kNHtcN481u6WkjeHjYtVeKVh2')\n",
    "change_script = p2pkh_script(change_h160)\n",
    "change_output = TxOut(amount=change_amount, script_pubkey=change_script)\n",
    "target_amount = int(0.1*100000000)\n",
    "target_h160 = decode_base58('mnrVtF8DWjMu839VW3rBfgYaAfKk8983Xf')\n",
    "target_script = p2pkh_script(target_h160)\n",
    "target_output = TxOut(amount=target_amount, script_pubkey=target_script)\n",
    "tx_obj = Tx(1, [tx_in], [change_output, target_output], 0, True)\n",
    "print(tx_obj)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ecc import PrivateKey\n",
    "from helper import SIGHASH_ALL\n",
    "z = transaction.sig_hash(0)\n",
    "private_key = PrivateKey(secret=8675309)\n",
    "der = private_key.sign(z).der()\n",
    "sig = der + SIGHASH_ALL.to_bytes(1, 'big')\n",
    "sec = private_key.point.sec()\n",
    "script_sig = Script([sig, sec])\n",
    "transaction.tx_ins[0].script_sig = script_sig \n",
    "print(transaction.serialize().hex())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from ecc import PrivateKey\n",
    "from helper import hash256, little_endian_to_int\n",
    "secret = little_endian_to_int(hash256(b'Jimmy Song secret'))\n",
    "private_key = PrivateKey(secret)\n",
    "print(private_key.point.address(testnet=True))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 3\n",
    "\n",
    "Write the `sign_input` method for the `Tx` class.\n",
    "\n",
    "#### Make [this test](/edit/code-ch07/tx.py) pass: `tx.py:TxTest:test_sign_input`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercise 3\n",
    "\n",
    "reload(tx)\n",
    "run(tx.TxTest(\"test_sign_input\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 4\n",
    "\n",
    "Create a testnet transaction that sends 60% of a single UTXO to `mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv`. The remaining amount minus fees should go back to your own change address. This should be a 1 input, 2 output transaction.\n",
    "\n",
    "You can broadcast the transaction at https://testnet.blockchain.info/pushtx"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercise 4\n",
    "\n",
    "from ecc import PrivateKey\n",
    "from helper import decode_base58, SIGHASH_ALL\n",
    "from script import p2pkh_script, Script\n",
    "from tx import TxIn, TxOut, Tx\n",
    "\n",
    "# create 1 TxIn and 2 TxOuts\n",
    "# 1 of the TxOuts should be back to your address\n",
    "# the other TxOut should be to this address\n",
    "target_address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv'\n",
    "\n",
    "# get the private key from the exercise in Chapter 4\n",
    "# change address should be the address generated from Chapter 4\n",
    "\n",
    "# get the prev_tx and prev_index from the transaction where you got\n",
    "# some testnet coins\n",
    "# create a transaction input for the previous transaction with\n",
    "# the default ScriptSig and sequence\n",
    "\n",
    "# target amount should be 60% of the output amount\n",
    "# set the fee to some reasonable amount\n",
    "# change amount = amount from the prev tx - target amount - fee\n",
    "\n",
    "# create a transaction output for the target amount and address\n",
    "# create a transaction output for the change amount and address\n",
    "# create the transaction object\n",
    "\n",
    "# sign the one input in the transaction object using the private key\n",
    "# print the transaction's serialization in hex\n",
    "# broadcast at http://testnet.blockchain.info/pushtx"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Exercise 5\n",
    "\n",
    "Advanced: get some more testnet coins from a testnet faucet and create a 2 input, 1 output transaction. 1 input should be from the faucet, the other should be from the previous exercise, the output can be your own address.\n",
    "\n",
    "You can broadcast the transaction at https://testnet.blockchain.info/pushtx"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Exercise 5\n",
    "\n",
    "from ecc import PrivateKey\n",
    "from helper import decode_base58, SIGHASH_ALL\n",
    "from script import p2pkh_script, Script\n",
    "from tx import TxIn, TxOut, Tx\n",
    "\n",
    "# Create 2 TxIns, 1 from the Exercise 4 and 1 from a testnet faucet\n",
    "# Creat 1 TxOut to the address above\n",
    "target_address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv'\n",
    "\n",
    "# get the private key from the exercise in Chapter 4\n",
    "\n",
    "# get the prev_tx and prev_index from the transaction where you got\n",
    "# some testnet coins\n",
    "# create the first transaction input with the default ScriptSig and\n",
    "# sequence\n",
    "# get the prev_tx and prev_index from the transaction in Exercise 4\n",
    "# create the second transaction input with the default ScriptSig and\n",
    "# sequence\n",
    "\n",
    "# set the fee to some reasonable amount\n",
    "# target amount should be the sum of the inputs - fee\n",
    "\n",
    "# create a transaction output for the amount and address\n",
    "\n",
    "# sign the first input using the private key\n",
    "# sign the second input using the private key \n",
    "# print the transaction's serialization in hex\n",
    "# broadcast at http://testnet.blockchain.info/pushtx"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
